#include "collision.h"
#include "zone.h"

#include "object.h"
#include "mapping.h"
#include "sprite.h"

#include "sonic.h"

#define SONIC_INJURY

extern byte v_lvllayout[];
extern byte v_256x256[];
extern byte v_16x16[];

extern byte *v_collindex;


// Collision data
extern byte AngleMap[];
extern byte CollArray1[];
extern byte CollArray2[];
extern byte Col_GHZ[];
extern byte Col_LZ[];
extern byte Col_MZ[];
extern byte Col_SLZ[];
extern byte Col_SYZ[];
extern byte Col_SBZ[];

byte *ColPointers[6] = { Col_GHZ, Col_LZ, Col_MZ, Col_SLZ, Col_SYZ, Col_SBZ };

#define SWAPWORD(val) (((val&0x00FF)<<8)+((val&0xFF00)>>8))
void ColIndexLoad(byte v_zone)
{
    v_collindex = ColPointers[v_zone];                          //this is v_zone*4 in ROM for size of long address
}

word *FindFloor(object *obj, word obYBottom, word obX, byte solidnessBit, word collisionFlags, signed short &floorDist, word offset, signed short *v_anglebufferPtr)
{
    word *nearestTile = FindNearestTile(obj, obYBottom, obX);

    word tileNum = SWAPWORD(*nearestTile);                      //get value for solidness, orientation and 16x16 tile number
    word solidOriBits = tileNum;
    tileNum = tileNum & 0x7FF;
    
    if (tileNum != 0)						//if the tile is not blank
    {
        if ((solidOriBits & (1<<solidnessBit)) == (1<<solidnessBit)) //and if the tile is solid
	{
            byte *v_collindexPtr = v_collindex;
	    byte colBlockNum = v_collindexPtr[tileNum] & 0xFF;  //get collision block number (for nearest tile)
            
            if (colBlockNum != 0)                               //branch if 0
            {             
	        byte *AngleMapPtr = AngleMap;
	        *v_anglebufferPtr = (signed char)AngleMapPtr[colBlockNum];       //get collision angle value (for this collision block type)
	   
	        word cArrayBlockOffset = colBlockNum * 16;		
	        word cArrayXOffset = obX;                           //get x-pos. of object

	        if ((solidOriBits & 0x800) == 0x800)              //is block flipped horizontally?
	        {
	            cArrayXOffset = ~cArrayXOffset;		    //account for this by logical NOT the array offset
		    *v_anglebufferPtr = -(*v_anglebufferPtr);	    //also negate collision angle
	        }
	        if ((solidOriBits & 0x1000) == 0x1000)              //is block flipped vertically?
	        {
                    *v_anglebufferPtr = (*v_anglebufferPtr + 0x40);
	            *v_anglebufferPtr = -(*v_anglebufferPtr);//negate and reverse collision angle 
	            *v_anglebufferPtr = (*v_anglebufferPtr - 0x40);
                }

	        cArrayXOffset = cArrayXOffset & 0xF;		//number of pixels offset RELATIVE TO 16X16 BLOCK 
	        word collArrayOffset = cArrayBlockOffset + cArrayXOffset; 
	    
	        byte *CollArray1Ptr = CollArray1;
	        signed char cHeight = (signed char)CollArray1Ptr[collArrayOffset];//get collision height (grabs height value at X offset for this collision block type)
                signed short collHeight = cHeight;                  //extended to a word in ROM	    

	        solidOriBits = solidOriBits ^ collisionFlags;       //apply collision flags...?
	        if ((solidOriBits & 0x1000) == 0x1000)              //is block flipped vertically?
	        {
		    collHeight = -collHeight;                       //negate collision height
	        }

	        if (collHeight != 0) 
                {		                                    //branch if height is 0 (nothing else to be done..)
	            if (collHeight < 0)   				//if height negative..
	            {
	                //@negfloor:
	                signed short yPixOffset = obYBottom & 0xF;	//
		        collHeight = collHeight + yPixOffset;
	                if (collHeight < 0)
		        {
	                    //@maxfloor:
		            signed short obYAboveNearest = obYBottom - offset;  //try tile above nearest
		            word *tileAboveNearest = FindFloor2(obj, obYAboveNearest, obX, solidnessBit, collisionFlags, floorDist, v_anglebufferPtr);
	                    floorDist = floorDist - 16;		        //return distance to floor
		            return tileAboveNearest;
	                }     
		        //else 
	                    //@isblank
	            }
	            else if (collHeight == 16)			        //if height max..
	            {
	                //@maxfloor:
		        signed short obYAboveNearest = obYBottom - offset;      //try tile above nearest
		        word *tileAboveNearest = FindFloor2(obj, obYAboveNearest, obX, solidnessBit, collisionFlags, floorDist, v_anglebufferPtr);
	                floorDist = floorDist - 16;		        //return distance to floor
		        return tileAboveNearest;
	            }
	            else
	            {
	                signed short yPixOffset = obYBottom & 0xF;	//get y pos of object
		        signed short cHeightobY = collHeight + yPixOffset;
		        floorDist = 0xF - cHeightobY;			//return distance to floor
	    	        return nearestTile; 
	            }
                }
            }
        }
    }
    
    //@isblank:, this point reached if nearest tile is a blank
    word obYBelowNearest = obYBottom + offset;                  //try tile below nearest
    word *tileBelowNearest = FindFloor2(obj, obYBelowNearest, obX, solidnessBit, collisionFlags, floorDist, v_anglebufferPtr);
    floorDist = floorDist + 16;		                        //return distance to floor
    return tileBelowNearest;
}

word *FindFloor2(object *obj, word obYBottom, word obX, byte solidnessBit, word collisionFlags, signed short &floorDist, signed short *v_anglebufferPtr)
{
    word *nearestTile = FindNearestTile(obj, obYBottom, obX);

    word tileNum = SWAPWORD(*nearestTile);                      //get value for solidness, orientation and 16x16 tile number
    word solidOriBits = tileNum;
    tileNum = tileNum & 0x7FF;
    
    if (tileNum != 0)						//if the tile is not blank
    {
        if ((solidOriBits & (1<<solidnessBit)) == (1<<solidnessBit)) //and if the tile is solid
	{
            byte *v_collindexPtr = v_collindex;
	    byte colBlockNum = v_collindexPtr[tileNum] & 0xFF;  //get collision block number (for nearest tile)
            
            if (colBlockNum != 0) 
            {                                                   //branch if 0
                byte *AngleMapPtr = AngleMap;
	        *v_anglebufferPtr = (signed char)AngleMapPtr[colBlockNum];       //get collision angle value (for this collision block type)
	   
                word cArrayBlockOffset = colBlockNum * 16;		
	        word cArrayXOffset = obX;                           //get x-pos. of object

                if ((solidOriBits & 0x800) == 0x800)              //is block flipped horizontally?
	        {
                    cArrayXOffset = ~cArrayXOffset;		    //account for this by logical NOT the array offset
		    *v_anglebufferPtr = -(*v_anglebufferPtr);	    //also negate collision angle
	        }
                if ((solidOriBits & 0x1000) == 0x1000)              //is block flipped vertically?
	        {
	            *v_anglebufferPtr = (*v_anglebufferPtr + 0x40);
	            *v_anglebufferPtr = -(*v_anglebufferPtr);       //negate and reverse collision angle 
	            *v_anglebufferPtr = (*v_anglebufferPtr - 0x40);
                }

                cArrayXOffset = cArrayXOffset & 0xF;		    //number of pixels offset RELATIVE TO 16X16 BLOCK 
	        word collArrayOffset = cArrayBlockOffset + cArrayXOffset; 
	    
                byte *CollArray1Ptr = CollArray1;
	        signed char cHeight = (signed char)CollArray1Ptr[collArrayOffset];//get collision height (grabs height value at X offset for this collision block type)
                signed short collHeight = cHeight;         
   
	        solidOriBits = solidOriBits ^ collisionFlags;       //apply collision flags...?
	        if ((solidOriBits & 0x1000) == 0x1000)              //is block flipped vertically?
	        {
	            collHeight = -collHeight;                       //negate collision height
                }

                if (collHeight != 0)
		{	                                            //branch if height is 0 (nothing else to be done..)
                    if (collHeight < 0)   			    //if height negative..
                    {
                        //@negfloor:
                        signed short yPixOffset = obYBottom & 0xF;	//
		        collHeight = collHeight + yPixOffset;
                        if (collHeight < 0)
		        {
                            //no max for findfloor2, so yPixOffset is actually just logical NOT distance to floor
		            floorDist = ~yPixOffset;
		            return nearestTile;
                        }     
		        //else 
                            //@isblank2
                    }
                    else
                    {
                        signed short yPixOffset = obYBottom & 0xF;	//get y pos of object
		        signed short cHeightobY = collHeight + yPixOffset;
		        floorDist = 0xF - cHeightobY;			//return distance to floor
	    	        return nearestTile; 
	            }
                }
            }
        }
    }

    //@isblank2:, this point reached if nearest tile is a blank
    floorDist = 0xF;
    signed short yPixOffset = obYBottom & 0xF;	//get y pos of object
    floorDist = floorDist - yPixOffset;
    return nearestTile;
}  

word *FindWall(object *obj, word obYBottom, word obX, byte solidnessBit, word collisionFlags, signed short &wallDist, word offset, signed short *v_anglebufferPtr)
{
    word *nearestTile = FindNearestTile(obj, obYBottom, obX);

    word tileNum = SWAPWORD(*nearestTile);                      //get value for solidness, orientation and 16x16 tile number
    word solidOriBits = tileNum;
    tileNum = tileNum & 0x7FF;
    
    if (tileNum != 0)						//if the tile is not blank
    {
        if ((solidOriBits & (1<<solidnessBit)) == (1<<solidnessBit)) //and if the tile is solid
	{
            byte *v_collindexPtr = v_collindex;
	    byte colBlockNum = v_collindexPtr[tileNum] & 0xFF;  //get collision block number (for nearest tile)
            
            if (colBlockNum != 0)                               //branch if 0
            {             
	        byte *AngleMapPtr = AngleMap;
	        *v_anglebufferPtr = AngleMapPtr[colBlockNum];       //get collision angle value (for this collision block type)
	   
	        word cArrayBlockOffset = colBlockNum * 16;		
	        word cArrayYOffset = obYBottom;                     //get y-pos. of object

	        if ((solidOriBits & 0x1000) == 0x1000)              //is block flipped vertically?
	        {
	            cArrayYOffset = ~cArrayYOffset;		    //account for this by logical NOT the array offset
		    *v_anglebufferPtr = -(*v_anglebufferPtr + 0x80);//also negate and reverse collision angle 
	        }
	        if ((solidOriBits & 0x800) == 0x800)              //is block flipped horizontally?
	        {
	            *v_anglebufferPtr = -(*v_anglebufferPtr);	    //negate collision angle
	        }

	        cArrayYOffset = cArrayYOffset & 0xF;		//number of pixels offset RELATIVE TO 16X16 BLOCK 
	        word collArrayOffset = cArrayBlockOffset + cArrayYOffset; 
	    
	        byte *CollArray2Ptr = CollArray2;
	        signed char cWidth = (signed char)CollArray2Ptr[collArrayOffset];//get collision width (grabs height value at Y offset for this collision block type)
                signed short collWidth = cWidth;	    
 
	        solidOriBits = solidOriBits ^ collisionFlags;       //apply collision flags...?
	        if ((solidOriBits & 0x800) == 0x800)              //is block flipped horizontally?
	        {
		    collWidth = -collWidth;                       //negate collision height/(width in this case)
	        }

	        if (collWidth != 0) 
                {		                                    //branch if height is 0 (nothing else to be done..)
	            if (collWidth < 0)   				//if height negative..
	            {
	                //@negfloor:
	                signed short xPixOffset = obX & 0xF;	        //get x pos of object
		        collWidth = collWidth + xPixOffset;
	                if (collWidth < 0)
		        {
	                    //@maxfloor:
		            signed short obXAboveNearest = obX - offset;        //try tile above nearest
		            word *tileAboveNearest = FindWall2(obj, obYBottom, obXAboveNearest, solidnessBit, collisionFlags, wallDist, v_anglebufferPtr);
	                    wallDist = wallDist - 16;		        //return distance to wall
		            return tileAboveNearest;
	                }     
		        //else 
	                    //@isblank
	            }
	            else if (collWidth == 16)			        //if height max..
	            {
	                //@maxfloor:
		        signed short obXAboveNearest = obX - offset;            //try tile above nearest
		        word *tileAboveNearest = FindWall2(obj, obYBottom, obXAboveNearest, solidnessBit, collisionFlags, wallDist, v_anglebufferPtr);
	                wallDist = wallDist - 16;		        //return distance to wall
		        return tileAboveNearest;
	            }
	            else
	            {
	                signed short xPixOffset = obX & 0xF;	        //get x pos of object
		        signed short cWidthobX = collWidth + xPixOffset;
		        wallDist = 0xF - cWidthobX;			//return distance to wall
	    	        return nearestTile; 
	            }
                }
            }
        }
    }
    
    //@isblank:, this point reached if nearest tile is a blank
    word obXBelowNearest = obX + offset;                        //try tile to left/right of nearest
    word *tileBelowNearest = FindWall2(obj, obYBottom, obXBelowNearest, solidnessBit, collisionFlags, wallDist, v_anglebufferPtr);
    wallDist = wallDist + 16;		                        //return distance to wall
    return tileBelowNearest;
}

word *FindWall2(object *obj, word obYBottom, word obX, byte solidnessBit, word collisionFlags, signed short &wallDist, signed short *v_anglebufferPtr)
{
    word *nearestTile = FindNearestTile(obj, obYBottom, obX);

    word tileNum = SWAPWORD(*nearestTile);                      //get value for solidness, orientation and 16x16 tile number
    word solidOriBits = tileNum;
    tileNum = tileNum & 0x7FF;
    
    if (tileNum != 0)						//if the tile is not blank
    {
        if ((solidOriBits & (1<<solidnessBit)) == (1<<solidnessBit)) //and if the tile is solid
	{
            byte *v_collindexPtr = v_collindex;
	    byte colBlockNum = v_collindexPtr[tileNum] & 0xFF;  //get collision block number (for nearest tile)
            
            if (colBlockNum != 0)                               //branch if 0
            {             
	        byte *AngleMapPtr = AngleMap;
	        *v_anglebufferPtr = AngleMapPtr[colBlockNum];       //get collision angle value (for this collision block type)
	   
	        word cArrayBlockOffset = colBlockNum * 16;		
	        word cArrayYOffset = obYBottom;                     //get y-pos. of object

	        if ((solidOriBits & 0x1000) == 0x1000)              //is block flipped vertically?
	        {
	            cArrayYOffset = ~cArrayYOffset;		    //account for this by logical NOT the array offset
		    *v_anglebufferPtr = -(*v_anglebufferPtr + 0x80);//also negate and reverse collision angle 
	        }
	        if ((solidOriBits & 0x800) == 0x800)              //is block flipped horizontally?
	        {
	            *v_anglebufferPtr = -(*v_anglebufferPtr);	    //negate collision angle
	        }

	        cArrayYOffset = cArrayYOffset & 0xF;		//number of pixels offset RELATIVE TO 16X16 BLOCK 
	        word collArrayOffset = cArrayBlockOffset + cArrayYOffset; 
	    
	        byte *CollArray2Ptr = CollArray2;
	        signed char cWidth = (signed char)CollArray2Ptr[collArrayOffset];//get collision width (grabs height value at Y offset for this collision block type)
                signed short collWidth = cWidth;	    

	        solidOriBits = solidOriBits ^ collisionFlags;       //apply collision flags...?
	        if ((solidOriBits & 0x800) == 0x800)              //is block flipped horizontally?
	        {
		    collWidth = -collWidth;                       //negate collision height/(width in this case)
	        }

	        if (collWidth != 0) 
                {		                                    //branch if height is 0 (nothing else to be done..)
	            if (collWidth < 0)   				//if height negative..
	            {
	                //@negfloor:
	                signed short xPixOffset = obX & 0xF;	        //get x pos of object
		        collWidth = collWidth + xPixOffset;
	                if (collWidth <= 0)
		        {
                            //no max for findwall2, so xPixOffset is actually just logical NOT distance to wall
		            wallDist = ~xPixOffset;
		            return nearestTile;
	                }     
		        //else 
	                    //@isblank2
	            }
	            else
	            {
	                signed short xPixOffset = obX & 0xF;	        //get x pos of object
		        signed short cWidthobX = collWidth + xPixOffset;
		        wallDist = 0xF - cWidthobX;			//return distance to wall
	    	        return nearestTile; 
	            }
                }
            }
        }
    }
    
    //@isblank:, this point reached if nearest tile is a blank
    wallDist = 0xF;    
    signed short xPixOffset = obX & 0xF;	            //get x pos of object
    wallDist = wallDist - xPixOffset;
    return nearestTile;
}


word *FindNearestTile(object *obj, word obYBottom, word obX)
{
    word chunkYOffset = (obYBottom >> 1) & 0x380;               //get y-pos. of bottom edge of object (to calculate y offset into level layout)
    word chunkXOffset = (obX >> 8) & 0x7F;                      //get x-pos. of object (to calculate x offset into level layout)
    word layoutIndex = chunkXOffset + chunkYOffset;             //combine
    
    signed char cur256 = -1;
    //cur256 = currentZone.v_lvllayout[layoutIndex];            //get 256x256 tile number
    cur256 = v_lvllayout[layoutIndex];                         
    
    if (cur256 == 0)       				        //blank tile
        //return (word*)&currentZone.v_16x16[0];                //return index 0
        return (word*)&v_16x16[0];
    else if (cur256 > 0)			                //normal tile
    {
        cur256 = cur256 - 1;					//skip index 0..
	word chunkIndex = (cur256 << 9);			//this is ror in ROM...
        word blockYOffset = (obYBottom << 1) & 0x1E0;			
	chunkIndex = chunkIndex + blockYOffset;
	word blockXOffset = (obX >> 3) & 0x1E;
	chunkIndex = chunkIndex + blockXOffset;

	//return (word*)&currentZone.v_256x256[chunkIndex];
        return (word*)&v_256x256[chunkIndex];
    }
    else						        //special tile
    {
         cur256 = cur256 & 0x7F; 		                //
         if ((obj->Render & 64) == 64)				//is object "behind a loop"?
	 {
             cur256 = cur256 + 1;
             if (cur256 == 0x29) 
                 cur256 = 0x51;
         }
         
	 //for some reason this is the same code in the asm for when we have a blank tile, except for the lack of ext.w on cur256 before ror'ing 
         cur256 = cur256 - 1;					//skip index 0..
	 word chunkIndex = (cur256 << 9);			//this is ror in ROM...
         word blockYOffset = (obYBottom << 1) & 0x1E0;			
	 chunkIndex = chunkIndex + blockYOffset;
	 word blockXOffset = (obX >> 3) & 0x1E;
	 chunkIndex = chunkIndex + blockXOffset;

	 //return (word*)&currentZone.v_256x256[chunkIndex];
         return (word*)&v_256x256[chunkIndex];
    }
}


extern object *objects;
#define player objects[0]

extern word v_debuguse;
extern bool f_lockmulti;

//; ---------------------------------------------------------------------------
//; Solid	object subroutine (includes spikes, blocks, rocks etc)
//;
//; input:
//;	d1 = width
//;	d2 = height / 2 (when jumping)
//;	d3 = height / 2 (when walking)
//;	d4 = x-axis position
//; ---------------------------------------------------------------------------

//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


//TODO:
//DOCUMENT THIS FUNCTION MORE
//USING PURPLE ROCK AS AN EXAMPLE: SONIC CAN PUSH FROM THE LEFT JUST FINE
//                                 SONIC SORT OF PUSHES FROM THE RIGHT BUT FLICKERS TO RUNNING FRAME
//                                 JUMPING ONTO A ROCK FAILS***
//SolidObject:
long SolidObject(object *obj, word width, word jumpHeight, word walkHeight, word xpos)
{
    //tst.b	obSolid(a0)	; is Sonic standing on the object?
    //beq.w	Solid_ChkEnter	; if not, branch
    if (obj->Solid != 0)               //sonic standing on rock, etc
    {
        //move.w	d1,d2
        //add.w	d2,d2
        word fullWidth = width * 2;

	//lea	(v_player).w,a1
        //object *player = &objects[0];

	//btst	#1,obStatus(a1)	; is Sonic in the air?
        //bne.s	@leave		; if yes, branch
        if ((player.Status & 2) == 0)
        {
	    //move.w	obX(a1),d0
            //sub.w	obX(a0),d0
            signed short distPlayerObjL = player.X - obj->X;
            
            //add.w	d1,d0
            signed short distPlayerObjR = (player.X - obj->X) + width;

	    //bmi.s	@leave		; if Sonic moves off the left, branch
            //cmp.w	d2,d0		; has Sonic moved off the right?
	    //bcs.s	@stand		; if not, branch
            if ((distPlayerObjR >= 0) && (distPlayerObjR < fullWidth))
            {
	        //@stand:
		//move.w	d4,d2
                word newPlatX = xpos;

		//bsr.w	MvSonicOnPtfm
		MvSonicOnPtfm(obj, newPlatX, walkHeight);

                //moveq	#0,d4
		return 0;

                //rts
            }	
        }

	//@leave:
        //bclr	#3,obStatus(a1)	; clear Sonic's standing flag
	player.Status = player.Status - (player.Status & 8);

        //bclr	#3,obStatus(a0)	; clear object's standing flag
	obj->Status = obj->Status - (obj->Status & 8);

        //clr.b	obSolid(a0)
        obj->Solid = 0;

	//moveq	#0,d4
        return 0;
                 
	//rts	
    }

    //Solid_ChkEnter:
    //tst.b	obRender(a0)
    //bpl.w	Solid_Ignore
    if (obj->Render >= 0x80)
    {
		
        //loc_FAD0:
        //lea	(v_player).w,a1
        //object *_player = &objects[0];

	//move.w	obX(a1),d0
	//sub.w	        obX(a0),d0
        signed short distPlayerObjL = player.X - obj->X;

	//add.w	d1,d0
        signed short distPlayerObjR = distPlayerObjL + width;

	//bmi.w	Solid_Ignore	; if Sonic moves off the left, branch
	if (distPlayerObjR >= 0)
        {
      	        //move.w	d1,d3
		//add.w	        d3,d3
                walkHeight = width * 2;

		//cmp.w	d3,d0		; has Sonic moved off the right?
                //bhi.w	Solid_Ignore	; if yes, branch
		if (distPlayerObjR < walkHeight)
                {
                    //move.b	obHeight(a1),d3
		    //ext.w	d3
                    word playerHeight = player.Height;

		    //add.w	d3,d2
                    word totalJumpHeight = jumpHeight + playerHeight;

		    //move.w	obY(a1),d3
		    //sub.w	obY(a0),d3
		    //addq.w	#4,d3
		    signed short distPlayerObjT = (player.Y - obj->Y) + 4;

                    //add.w	d2,d3
		    signed short distPlayerObjB = distPlayerObjT + totalJumpHeight;

                    //bmi.w	Solid_Ignore	; if Sonic moves above, branch
		    if (distPlayerObjB >= 0)
                    {    
                        //move.w	d2,d4
		        //add.w	d4,d4
                        word fullJumpHeight = totalJumpHeight * 2;

		        //cmp.w	d4,d3		; has Sonic moved below?
                        //bcc.w	Solid_Ignore	; if yes, branch
                        if (distPlayerObjB <= fullJumpHeight)
                        {
		            //loc_FB0E:
		            //tst.b	(f_lockmulti).w	; are controls locked?
                            //bmi.w	Solid_Ignore	; if yes, branch
		            
                            if (!f_lockmulti)
		            {
                                //cmpi.b	#6,(v_player+obRoutine).w ; is Sonic dying?
		                if (player.Routine != 6)
                                {
                                    //if Revision=0
		                    //bcc.w	Solid_Ignore	; if yes, branch
		                    //else
			            //bcc.w	Solid_Debug
		                    //endc
		
                                    //tst.w	(v_debuguse).w	; is debug mode being used?
		                    //bne.w	Solid_Debug	; if yes, branch
		                    if (v_debuguse == 0)
                                    {
                                        //move.w	d0,d5
                                        signed short d5 = distPlayerObjR;                       
                 
		                        //cmp.w	d0,d1		; is Sonic right of centre of object?
		                        //bcc.s	@isright	; if yes, branch
                                        if (width < distPlayerObjR)
                                        {
                                            //add.w	d1,d1
                                            word fullWidth = width * 2;
                                            
		                            //sub.w	d1,d0 
                                            distPlayerObjR = distPlayerObjR - fullWidth;

		                            //move.w	d0,d5
                                            //neg.w	d5
                                            d5 = -(distPlayerObjR);
                                        }

	                                //@isright:
		                        //move.w	d3,d1
                                        signed short d1 = distPlayerObjB;

		                        //cmp.w	d3,d2		; is Sonic below centre of object?
                                        //bcc.s	@isbelow	; if yes, branch
                                        if (totalJumpHeight <= distPlayerObjB) 
		                        {
                                            //subq.w	#4,d3
		                            //sub.w	d4,d3
		                            //move.w	d3,d1
                                            distPlayerObjB = (distPlayerObjB - 4) - fullJumpHeight;
                                            
                                            //neg.w	d1
                                            d1 = -(distPlayerObjB);
                                        }
	                               
                                        //@isbelow:
		                        //cmp.w	d1,d5
                                        //bhi.w	Solid_TopBottom	; if Sonic hits top or bottom, branch
		                        if (d5 < d1)
                                        {
                                            //cmpi.w	#4,d1
		                            //bls.s	Solid_SideAir
                                            if (d1 >= 4)
                                            {
		                                //tst.w	d0		; where is Sonic?
		                                //beq.s	Solid_Centre	; if inside the object, branch
                                                if (distPlayerObjR != 0)
                                                {
                                                    //bmi.s	Solid_Right	; if right of the object, branch
                                                        //Solid_Right: 
                                                        //tst.w	    obVelX(a1)	; is Sonic moving right?
		                                        //bpl.s	    Solid_Centre; if yes, branch
                                                    //tst.w	obVelX(a1)	; is Sonic moving left?
		                                    //bmi.s	Solid_Centre	; if yes, branch
                                                    if (player.VelocityX >= 0 || ((distPlayerObjR < 0) && (player.VelocityX < 0)))
                                                    {
                                                        //bra.s	Solid_Left
                                                        // ; ===========================================================================
                                                        //Solid_Left:
		                                        //move.w	#0,obInertia(a1)
                                                        player.Inertia = 0;

		                                        //move.w	#0,obVelX(a1)	; stop Sonic moving
                                                        player.VelocityX = 0;
                                                    }
                                                }
                                               
                                                //Solid_Centre:
		                                //sub.w	d0,obX(a1)	; correct Sonic's position
                                                player.X = player.X - distPlayerObjR;

		                                //btst	#1,obStatus(a1)	; is Sonic in the air?
                                                //bne.s	Solid_SideAir	; if yes, branch
                                                if ((player.Status & 2) == 2)
                                                {
                                                    //Solid_SideAir:
		                                    //bsr.s	Solid_NotPushing
                                                    //Solid_NotPushing:
		                                    //bclr	#5,obStatus(a0)	; clear pushing flag
                                                    obj->Status = obj->Status - (obj->Status & 32);

		                                    //bclr	#5,obStatus(a1)	; clear Sonic's pushing flag
		                                    player.Status = player.Status - (player.Status & 32);

                                                    //moveq	#1,d4		; return side collision
                                                    return 1;
             
		                                    //rts
                                                }	
		                                else
                                                {
                 	                            //bset	#5,obStatus(a1)	; make Sonic push object
                                                    player.Status = player.Status | 32;

		                                    //bset	#5,obStatus(a0)	; make object be pushed
                                                    obj->Status = obj->Status | 32;

		                                    //moveq	#1,d4		; return side collision
                                                    return 1;
   
		                                    //rts
                                                }
                                            }
                                            else
                                            {
                                                //Solid_SideAir:
		                                //bsr.s	Solid_NotPushing
                                                //Solid_NotPushing:
		                                //bclr	#5,obStatus(a0)	; clear pushing flag
                                                obj->Status = obj->Status - (obj->Status & 32);

		                                //bclr	#5,obStatus(a1)	; clear Sonic's pushing flag
		                                player.Status = player.Status - (player.Status & 32);

                                                //moveq	#1,d4		; return side collision
                                                return 1;
             
		                                //rts
                                            }   //; ===========================================================================
                                        }
                                        else
                                        {
                                            //Solid_TopBottom:
		                            //tst.w	d3		; is Sonic below the object?
                                            //bmi.s	Solid_Below	; if yes, branch
                                            if (distPlayerObjB < 0)
                                            {
		                                //Solid_Below:
		                                //tst.w	obVelY(a1)	; is Sonic moving vertically?
                                                //beq.s	Solid_Squash	; if not, branch
		                                if (player.VelocityY != 0)
                                                {
                                                    //bpl.s	Solid_TopBtmAir	; if moving downwards, branch
                                                    //tst.w	d3		; is Sonic above the object?
		                                    //bpl.s	Solid_TopBtmAir	; if yes, branch
                                                    if ((player.VelocityY < 0) && (distPlayerObjB < 0))
		                                    {
                                                        //sub.w	d3,obY(a1)	; correct Sonic's position
                                                        player.Y = player.Y - distPlayerObjB;
   
                                                        //move.w	#0,obVelY(a1)	; stop Sonic moving
                                                        player.VelocityY = 0;
                                                    }

                                                    //Solid_TopBtmAir:
		                                    //moveq	#-1,d4
                                                    return -1;
               
                                                    //rts	
                                                }
                                                else
                                                {
                                                    //Solid_Squash:
		                                    //btst	#1,obStatus(a1)	; is Sonic in the air?
		                                    //bne.s	Solid_TopBtmAir	; if yes, branch
                                                    if ((player.Status & 2) == 0)
		                                    {
                                                        //move.l	a0,-(sp)
		                                        //movea.l	a1,a0
		                                        //jsr	KillSonic	; kill Sonic
		                                        //movea.l	(sp)+,a0
		                                        //moveq	#-1,d4
                                                        return -1;
		                                       
                                                        //rts
                                                    }	
                                                    else
                                                    {
                                                        //Solid_TopBtmAir:
		                                        //moveq	#-1,d4
                                                        return -1;
		                                    }
                                                }
                                            }
                                            else if (distPlayerObjB < 16) 
                                            {
                                                //cmpi.w	#$10,d3		; has Sonic landed on the object?
		                                //bcs.s	Solid_Landed	; if yes, branch
                                                //Solid_Landed:

		                                //subq.w	#4,d3
                                                distPlayerObjB = distPlayerObjB - 4;

		                                //moveq	#0,d1
		                                //move.b	obActWid(a0),d1
                                                byte actionWidth = obj->ActionWidth;

		                                //move.w	d1,d2
		                                //add.w	d2,d2
                                                word dblActionWidth = actionWidth * 2;

		                                //add.w	obX(a1),d1
                                                //sub.w	obX(a0),d1
                                                signed short distPlayerObjR2 = actionWidth + (player.X - obj->X);

		                                //bmi.s	Solid_Miss	; if Sonic is right of object, branch
                                                //cmp.w	d2,d1		; is Sonic left of object?
						//bcc.s	Solid_Miss	; if yes, branch
						//tst.w	obVelY(a1)	; is Sonic moving upwards?
						//bmi.s	Solid_Miss	; if yes, branch
                                                if ((distPlayerObjR2 >= 0) && (distPlayerObjR2 <= dblActionWidth) && (player.VelocityY >= 0))
                                                {
                                                    //sub.w	d3,obY(a1)	; correct Sonic's position
                                                    player.Y = player.Y - distPlayerObjB;

		                                    //subq.w	#1,obY(a1)
                                                    player.Y = player.Y - 1;

		                                    //bsr.s	Solid_ResetFloor
                                                    Solid_ResetFloor(obj);
		
                                                    //move.b	#2,obSolid(a0) ; set standing flags
                                                    obj->Solid = 2;
		
                                                    //bset	#3,obStatus(a0)
                                                    obj->Status = obj->Status | 8;

		                                    //moveq	#-1,d4		; return top/bottom collision
                                                    return -1;
		                                     
                                                    //rts	
                                                    //; ===========================================================================

                                                }
                                                else
                                                {
                                                    //Solid_Miss:
		                                    //moveq	#0,d4
		                                    return 0;
                                                    //rts	                            
                                                }
                                            }
                                            else
                                            {
		                                //bra.s	Solid_Ignore
                                            }
                                        }
                                    }
                                    else
                                    {
                                        //Solid_Debug:
		                        //moveq	#0,d4		; return no collision
		                        return 0;

                                        //rts
                                    }
                                }

                            }
                        }
                    }
                }
        }
    }
     
    //Solid_Ignore:
    //btst	#5,obStatus(a0)	; is Sonic pushing?
    //beq.s	Solid_Debug	; if not, branch
    if ((player.Status & 32) == 32)
    {
        //move.w	#id_Run,obAnim(a1) ; use running animation
        player.Anim = id_Run;

        //Solid_NotPushing:
        //bclr	#5,obStatus(a0)	; clear pushing flag
        obj->Status = obj->Status - (obj->Status & 32);
 
        //bclr	#5,obStatus(a1)	; clear Sonic's pushing flag
        player.Status = player.Status - (player.Status & 32);
    }



    //Solid_Debug:
    //moveq	#0,d4		; return no collision
    return 0;

}    //rts	; End of function SolidObject


//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


//Solid_ResetFloor:
void Solid_ResetFloor(object *obj)
{
    //btst	#3,obStatus(a1)	; is Sonic standing on something?
    //beq.s	@notonobj	; if not, branch
    if ((player.Status & 8) == 8)
    {
        //moveq	#0,d0
	//move.b	$3D(a1),d0	; get object being stood on
        byte standObjIndex = player.Variables[0x3D-0x28];

	//lsl.w	#6,d0
	//addi.l	#(v_objspace&$FFFFFF),d0
	//movea.l	d0,a2
        object *standObj = &objects[standObjIndex];

	//bclr	#3,obStatus(a2)	; clear object's standing flags
        standObj->Status = standObj->Status - (standObj->Status & 8);

	//clr.b	obSolid(a2)
        standObj->Solid = 0;
    }

    //@notonobj:
    //move.w	a0,d0
    //subi.w	#$D000,d0
    //lsr.w	#6,d0
    //andi.w	#$7F,d0
    word standObjIndex = obj-objects;	

    //move.b	d0,$3D(a1)	; set object being stood on
    player.Variables[0x3D-0x28] = standObjIndex;
	
    //move.b	#0,obAngle(a1)	; clear Sonic's angle
    player.Angle = 0;
	
    //move.w	#0,obVelY(a1)	; stop Sonic
    player.VelocityY = 0;
	
    //move.w	obVelX(a1),obInertia(a1)
    player.Inertia = player.VelocityX;
		
    //btst	#1,obStatus(a1)	; is Sonic in the air?
    //beq.s	@notinair	; if not, branch
    if ((player.Status & 2) == 2)
    {
        //move.l	a0,-(sp)
	//movea.l	a1,a0
	//jsr	Sonic_ResetOnFloor ; reset Sonic as if on floor
        Sonic_ResetOnFloor();
	
	//movea.l	(sp)+,a0
    }
  
    else
    {
        //@notinair:
        //bset	#3,obStatus(a1)	; set object standing flag
        obj->Status = obj->Status | 8;
	
        //bset	#3,obStatus(a0)	; set Sonic standing on object flag
        player.Status = player.Status | 8;
    }
}   //rts	
//; End of function Solid_ResetFloor

/*; ===========================================================================

SolidObject71:				; XREF: Obj71_Solid
		tst.b	obSolid(a0)
		beq.w	loc_FAD0
		move.w	d1,d2
		add.w	d2,d2
		lea	(v_player).w,a1
		btst	#1,obStatus(a1)
		bne.s	@leave
		move.w	obX(a1),d0
		sub.w	obX(a0),d0
		add.w	d1,d0
		bmi.s	@leave
		cmp.w	d2,d0
		bcs.s	@stand

	@leave:
		bclr	#3,obStatus(a1)
		bclr	#3,obStatus(a0)
		clr.b	obSolid(a0)
		moveq	#0,d4
		rts	

	@stand:
		move.w	d4,d2
		bsr.w	MvSonicOnPtfm
		moveq	#0,d4
		rts	
; ===========================================================================

SolidObject2F:				; XREF: Obj2F_Solid
		lea	(v_player).w,a1
		tst.b	obRender(a0)
		bpl.w	Solid_Ignore
		move.w	obX(a1),d0
		sub.w	obX(a0),d0
		add.w	d1,d0
		bmi.w	Solid_Ignore
		move.w	d1,d3
		add.w	d3,d3
		cmp.w	d3,d0
		bhi.w	Solid_Ignore
		move.w	d0,d5
		btst	#0,obRender(a0)	; is object horizontally flipped?
		beq.s	@notflipped	; if not, branch
		not.w	d5
		add.w	d3,d5

	@notflipped:
		lsr.w	#1,d5
		moveq	#0,d3
		move.b	(a2,d5.w),d3
		sub.b	(a2),d3
		move.w	obY(a0),d5
		sub.w	d3,d5
		move.b	obHeight(a1),d3
		ext.w	d3
		add.w	d3,d2
		move.w	obY(a1),d3
		sub.w	d5,d3
		addq.w	#4,d3
		add.w	d2,d3
		bmi.w	Solid_Ignore
		move.w	d2,d4
		add.w	d4,d4
		cmp.w	d4,d3
		bcc.w	Solid_Ignore
		bra.w	loc_FB0E
; ===========================================================================*/

//---HERE STARTS ROUTINES HANDLING COLLISION WITH PLATFORM OBJECTS---//


extern bool f_lockmulti;

//; ---------------------------------------------------------------------------
//; Platform subroutine
//; ---------------------------------------------------------------------------

//PlatformObject:
void PlatformObject(object *obj, word dist)
{
    //lea	(v_player).w,a1
    //tst.w	obVelY(a1)	; is Sonic moving up/jumping?
    //bmi.w	Plat_Exit	; if yes, branch
    if (player.VelocityY >= 0)
    {
        //;		perform x-axis range check
	//move.w	obX(a1),d0
        //sub.w	        obX(a0),d0
        signed short distPlayerPlatformX = player.X - obj->X;
 
	//add.w	d1,d0
        signed short totalDist = distPlayerPlatformX + dist;

	//bmi.w	Plat_Exit
        if (totalDist >= 0)
        {
	    //add.w	d1,d1
            word doubleDist = dist * 2;

	    //cmp.w	d1,d0
	    //bhs.w	Plat_Exit
            if (totalDist <= doubleDist)
            {
	        //Plat_NoXCheck:
	        Plat_NoXCheck(obj);
            }
        }	
    }
    //Plat_Exit:
    //rts	
}   //; End of function PlatformObject

void Plat_NoXCheck(object *obj)
{
    //move.w	obY(a0),d0
    //subq.w	#8,d0
    word platformY = obj->Y - 8;      //8 pixels above platform

    Platform3(obj, platformY);
}

void Platform3(object *obj, word platformY)
{
    //Platform3:
    //;		perform y-axis range check
    //move.w	obY(a1),d2
    word playerY = player.Y;

    //move.b	obHeight(a1),d1
    //ext.w	d1
    word playerHeight = player.Height;

    //add.w	d2,d1
    //addq.w	#4,d1
    word playerBtm = playerY + playerHeight + 4;    //4 pixels below player

    //sub.w	d1,d0
    signed short distPlatformPlayerY = platformY - playerBtm;    //= 0 when 12 pixels between bottom of player and top of platform, < 0 when
                                                                 //> 0 when > 12 pixels between bottom of player and top of platform, 
    //bhi.w	Plat_Exit                                        //< 0 when < 12 pixels between bottom of player and top of platform
    //cmpi.w	#-$10,d0                                         //< -16 when player more than 4 pixels below top of platform
    //blo.w	Plat_Exit
    if (distPlatformPlayerY < 0 && distPlatformPlayerY >= -16)
    {
        //tst.b	(f_lockmulti).w
        //bmi.w	Plat_Exit
        //cmpi.b	#6,obRoutine(a1)
        //bhs.w	Plat_Exit
        if (!f_lockmulti && player.Routine < 6)
        { 
            //add.w	d0,d2
            //addq.w	#3,d2
            word repositionY = distPlatformPlayerY + playerY + 3;

	    //move.w	d2,obY(a1)
            player.Y = repositionY;

	    //addq.b	#2,obRoutine(a0)
            obj->Routine = obj->Routine + 2;
            
            loc_74AE(obj);
        }
    }
}

void loc_74AE(object *obj)                                     //for platforms...
{
    //loc_74AE:
    //btst	#3,obStatus(a1)
    //beq.s	loc_74DC
    if ((player.Status & 8) == 8)                              //if sonic already on an object that should stop him from falling, like a platform or a bridge
    {
        //moveq	#0,d0
	//move.b	$3D(a1),d0
        byte standObjID = player.Variables[0x3D - 0x28];                 //change object attributes to reflect sonic no longer standing on it
        
	//lsl.w	#6,d0
	//addi.l	#v_objspace&$FFFFFF,d0
	//movea.l	d0,a2
        object *standObj = &objects[standObjID];

	//bclr	#3,obStatus(a2)
        standObj->Status = standObj->Status - (standObj->Status & 8);

	//clr.b	ob2ndRout(a2)
        standObj->secondRoutine = 0;

	//cmpi.b	#4,obRoutine(a2)
        //bne.s	loc_74DC
        if (standObj->Routine == 4)
	{	
	    //subq.b	#2,obRoutine(a2)
            standObj->Routine = standObj->Routine - 2;
        }
    }

    //loc_74DC:
    //move.w	a0,d0
    //subi.w	#-$3000,d0
    //lsr.w	#6,d0
    //andi.w	#$7F,d0
    word obIndex = (obj - &objects[0]);       //grab index of platform object

    //move.b	d0,$3D(a1)
    player.Variables[0x3D-0x28] = obIndex;    //sonic now standing on this object

    //move.b	#0,obAngle(a1)
    player.Angle = 0;                         //(at an angle right side up, all platforms are flat)

    //move.w	#0,obVelY(a1)
    player.VelocityY = 0;                     //(keep sonic from falling)

    //move.w	obVelX(a1),obInertia(a1)
    player.Inertia = player.VelocityX;        //(sonic now picks up speed at a rate defined only by x-velocity)

    //btst	#1,obStatus(a1)
    //beq.s	loc_7512
    if ((player.Status & 2) == 2)             //if sonic still thinks hes in the air (which may be the case since solidity for objs works separate)
    {
	//move.l	a0,-(sp)
	//movea.l	a1,a0
	//jsr	Sonic_ResetOnFloor
	Sonic_ResetOnFloor();                 //reset him on the floor
          
        //movea.l	(sp)+,a0
    }
             
    //loc_7512:
    //bset	#3,obStatus(a1)
    player.Status = player.Status | 8;        //now officially change flags for sonic standing on solid object

    //bset	#3,obStatus(a0)
    obj->Status = obj->Status | 8;            //also change flag for object being stood on
}

//; ---------------------------------------------------------------------------
//; Sloped platform subroutine (GHZ collapsing ledges and	SLZ seesaws)
//; ---------------------------------------------------------------------------

//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||

#define distPlayerObjX distPlayerObjR

//SlopeObject:				; XREF: Obj1A_Slope; Obj5E_Slope
void SlopeObject(object *obj, word width, byte *slopeData)
{
    //lea	(v_player).w,a1
    //tst.w	obVelY(a1)
    //bmi.w	Plat_Exit
    if (player.VelocityY < 0) { /*Plat_Exit();*/ }
    else
    {	
        //move.w	obX(a1),d0
	//sub.w	        obX(a0),d0
        signed short distPlayerObjL = player.X - obj->X;
   
	//add.w	d1,d0
        signed short distPlayerObjR = distPlayerObjL + width;

	//bmi.s	Plat_Exit
        if (distPlayerObjR >= 0)
        {
	    //add.w	d1,d1
            word fullWidth = width * 2;

	    //cmp.w	d1,d0
            //bhs.s	Plat_Exit
            if (distPlayerObjR < fullWidth)
            {
	        //btst	#0,obRender(a0)
                //beq.s	loc_754A
                if ((obj->Render & 1) == 1)
                {
		    //not.w	d0
                    signed short rDistPlayerObjR = ~distPlayerObjR;

		    //add.w	d1,d0
                    distPlayerObjX = rDistPlayerObjR + fullWidth;
                }
            
                //loc_754A:
		//lsr.w	#1,d0
                word slopeDataIndex = distPlayerObjX/2;

		//moveq	#0,d3
		//move.b	(a2,d0.w),d3
                byte slopeValue = slopeData[slopeDataIndex];

		//move.w	obY(a0),d0
                //sub.w	d3,d0
                signed short repositionY = obj->Y - slopeValue;
            
		//bra.w	Platform3
                Platform3(obj, repositionY);

            }    
        }
    }
}         //; End of function SlopeObject



//; ---------------------------------------------------------------------------
//; Sloped platform subroutine (GHZ collapsing ledges and	MZ platforms)
//; ---------------------------------------------------------------------------

//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||

//SlopeObject2:				; XREF: Obj1A_WalkOff; et al
void SlopeObject2(object *obj, word width, word slopex, byte *slopeData)
{
    //lea	(v_player).w,a1
    //btst	#3,obStatus(a1)
    //beq.s	locret_856E
    if ((player.Status & 8) == 0) { /*locret_856E*/ }
    else
    {	
        //move.w	obX(a1),d0
	//sub.w	        obX(a0),d0
        signed short distPlayerObjL = player.X - obj->X;

	//add.w	d1,d0
        signed short distPlayerObjR = distPlayerObjL + width;

	//lsr.w	#1,d0
        distPlayerObjX = distPlayerObjR/2;
                
	//btst	#0,obRender(a0)
        //beq.s	loc_854E
        if ((obj->Render & 1) == 1)
        {
            //not.w	d0
            signed short rDistPlayerObjR = ~distPlayerObjX;

	    //add.w	d1,d0
            distPlayerObjX = rDistPlayerObjR + width;
        }
            
        //loc_854E:
	//moveq	#0,d1
	//move.b	(a2,d0.w),d1
        byte slopeValue = slopeData[distPlayerObjX];

	//move.w	obY(a0),d0
        //sub.w	d1,d0
        signed short repositionY = obj->Y - slopeValue;
          
        //starting what would take place of platform3...  
        //moveq	#0,d1
	//move.b	obHeight(a1),d1
        byte playerHeight = player.Height;

	//sub.w	d1,d0
        signed short playerTop = repositionY - playerHeight;
		
        //move.w	d0,obY(a1)
        player.Y = playerTop;

	//sub.w	obX(a0),d2
        signed short shiftX = obj->X - slopex;

	//sub.w	d2,obX(a1)
        player.X = player.X - shiftX;
    }

    //locret_856E:
    //rts	
}   //; End of function SlopeObject2

//; ===========================================================================
/*
; ---------------------------------------------------------------------------
; Collision data for GHZ collapsing ledge
; ---------------------------------------------------------------------------
Ledge_SlopeData:
		incbin	"misc\GHZ Collapsing Ledge Heightmap.bin"
		even

		include	"_maps\Collapsing Ledge.asm"
		include	"_maps\Collapsing Floors.asm"

		include	"_incObj\1C Scenery.asm"
		include	"_maps\Scenery.asm"

		include	"_incObj\1D Unused Switch.asm"
		include	"_maps\Unused Switch.asm"

		include	"_incObj\2A SBZ Small Door.asm"
		include	"_anim\SBZ Small Door.asm"
		include	"_maps\SBZ Small Door.asm"
*/

//; ---------------------------------------------------------------------------
//; Subroutine allowing Sonic to walk or jump off a platform
//; ---------------------------------------------------------------------------

//ExitPlatform:
bool ExitPlatform(object *platform, word actionWidth, signed short &distPlayerLPlatformX)
{
    //move.w	d1,d2
    word _actionWidth = actionWidth;

    return ExitPlatform2(platform, _actionWidth, actionWidth, distPlayerLPlatformX);
}
                            //bridgeHalf = 96 = (16*6) bridgeMiddle = 104 = (96+8) 
bool ExitPlatform2(object *platform, word actionWidth, word actionWidth2, signed short &distPlayerLPlatformX)
{
    //bool exitLeft = true;

    //ExitPlatform2:
    //add.w	d2,d2
    word fullWidth = actionWidth * 2;        //192 pix, full bridge dist (96*2)

    //lea	(v_player).w,a1
    //btst	#1,obStatus(a1)
    //bne.s	loc_75E0
    if ((player.Status & 2) == 0)       //Set if Sonic is in the air (jump counts).
    {
        //move.w	obX(a1),d0
	//sub.w	        obX(a0),d0                                 //leftlog = (platform->X - 96) : platform->X = leftlog + 96
        signed short distPlayerPlatformX = player.X - platform->X; //distPlayerPlatformX = player.X - (leftlog + 96)

	//add.w	d1,d0
        distPlayerLPlatformX = distPlayerPlatformX + actionWidth2; //distPlayerLPlatformX = (player.X - (leftlog + 96)) + 104
                                                                   //                     = (player.X - leftlog) + 8
                                                                   // (player.X - leftlog) + 8 < 0          ---> player.X - leftlog < -8                     (if player left more than 8 pix left of bridge left)
	//bmi.s	loc_75E0                                           // (player.X - leftlog) + 8 >= fullWidth ---> player.X - leftlog >= (fullWidth - 8 = 184) (if player left less than 8 pix left of bridge right) 
        //cmp.w	d2,d0
	//blo.s	locret_75F2
        if (distPlayerLPlatformX >= 0)
        {
            //exitLeft = false;
            if (distPlayerLPlatformX < fullWidth)
            {
                return false;
            }
        }
    }
    
    //loc_75E0:
    //bclr	#3,obStatus(a1)
    player.Status = player.Status - (player.Status & 8);

    //move.b	#2,obRoutine(a0)
    platform->Routine = 2;
 
    //bclr	#3,obStatus(a0)
    platform->Status = platform->Status - (platform->Status & 8);

    //locret_75F2:
    //rts	
    return true;

}   //; End of function ExitPlatform

//; ---------------------------------------------------------------------------
//; Subroutine to	change Sonic's position with a platform
//; ---------------------------------------------------------------------------

//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


//MvSonicOnPtfm:
void MvSonicOnPtfm(object *obj, word newX, signed short platHeight)
{
    //lea	(v_player).w,a1
    //move.w	obY(a0),d0
    //sub.w	d3,d0
    signed short platTop = obj->Y - platHeight;

    //bra.s	MvSonic2
    MvSonic2(obj, platTop, newX);
 
}   //; End of function MvSonicOnPtfm

//; ---------------------------------------------------------------------------
//; Subroutine to	change Sonic's position with a platform
//; ---------------------------------------------------------------------------

//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


//MvSonicOnPtfm2:
void MvSonicOnPtfm2(object *obj, word newX)
{
    //lea	(v_player).w,a1
    //move.w	obY(a0),d0
    //subi.w	#9,d0
    signed short platTop = obj->Y - 9;
    
    MvSonic2(obj, platTop, newX);
}

//MvSonic2:
void MvSonic2(object *obj, signed short platTop, word newX)
{
    //tst.b	(f_lockmulti).w
    //bmi.s	locret_7B62
    //cmpi.b	#6,(v_player+obRoutine).w
    //bhs.s	locret_7B62
    //tst.w	(v_debuguse).w
    //bne.s	locret_7B62
    if ((!f_lockmulti) && (player.Routine < 6) && (v_debuguse == 0))
    { 
        //moveq	#0,d1
	//move.b	obHeight(a1),d1
        byte playerHeight = player.Height;

	//sub.w	d1,d0
        signed short repositionY = platTop - playerHeight;

	//move.w	d0,obY(a1)
        player.Y = repositionY;

	//sub.w	obX(a0),d2
        signed short offsetX = newX - obj->X;
 
	//sub.w	d2,obX(a1)
        player.X = player.X - offsetX;
    }

    //locret_7B62:
    //rts	
}   //; End of function MvSonicOnPtfm2*/

//---HERE STARTS THE HANDLING ROUTINE FOR CHECKING SONIC AGAINST EACH OBJECT FOR COLLISION---//

extern byte v_invinc;
extern word v_itembonus;

//ReactToItem:				; XREF: SonicPlayer
long ReactToItem()
{
    //nop
    asm volatile ("nop");
	
    //move.w	obX(a0),d2	; load Sonic's x-axis position
    word obX = player.X;

    //move.w	obY(a0),d3	; load Sonic's y-axis position
    word obY = player.Y;

    //subq.w	#8,d2
    signed short playerXBehind = obX - 8;

    //moveq	#0,d5
    //move.b	obHeight(a0),d5	; load Sonic's height
    //subq.b	#3,d5
    byte scaledHeight = player.Height - 3;

    //sub.w	d5,d3
    signed short playerYAbove = obY - scaledHeight;

    //cmpi.b	#fr_Duck,obFrame(a0) ; is Sonic ducking?
    //bne.s	@notducking	; if not, branch
    if (player.Frame == fr_Duck)
    {
        //addi.w	#$C,d3
        playerYAbove = playerYAbove + 0xC;
  
	//moveq	#$A,d5
        scaledHeight = 10;
    }
    
    //@notducking:
    //move.w	#$10,d4
    word d4 = 16;

    //add.w	d5,d5
    word doubleScaleHeight = scaledHeight * 2;

    //lea	(v_objspace+$800).w,a1 ; set object RAM start address
    object *curObject = &objects[1]; 
   
    //move.w	#$5F,d6
    signed short objCount = 0x5F;

    //@loop:
    for (int curObjNum = 0; objCount >= 0; objCount--, curObjNum++)
    {
        //tst.b	obRender(a1)
        //bpl.s	@next
        if ((signed char)curObject->Render < 0)
        {
            //move.b	obColType(a1),d0 ; load collision type
            byte obColType = curObject->ColType;
        
	    //bne.s	@proximity	; if nonzero, branch
            if (obColType != 0)
            {
                if (TestCollision(curObject, obColType, d4, doubleScaleHeight, playerXBehind, playerYAbove))      //TestCollision is (@proximity - @withiny), false skips past @withiny and continues with @next
                {
                    //@withiny:
	            //@chktype:
		    //move.b	obColType(a1),d1 ; load collision type
		    //andi.b	#$C0,d1		; is obColType $40 or higher?
                    byte obColTypeCmp = curObject->ColType & 0xC0;
               
		    //beq.w	React_Enemy	; if not, branch
                    //cmpi.b	#$C0,d1		; is obColType $C0 or higher?
		    //beq.w	React_Special	; if yes, branch
                    //tst.b	d1		; is obColType $80-$BF?
		    //bmi.w	React_ChkHurt	; if yes, branch
                    if (obColTypeCmp == 0) { React_Enemy(curObject); }
                    else if (obColTypeCmp == 0xC0) { /*React_Special*/ }
                    else if (obColTypeCmp >= 0x80) { React_ChkHurt(curObject); }
                    else
                    {
                        //; obColType is $40-$7F (powerups)

		        //move.b	obColType(a1),d0
                        //andi.b	#$3F,d0
                        byte _obColType = curObject->ColType & 0x3F;

		        //cmpi.b	#6,d0		; is collision type $46	?
                        //beq.s	React_Monitor	; if yes, branch
                        //cmpi.w	#90,$30(a0)	; is Sonic invincible?
		        //bcc.w	@invincible	; if yes, branch
                        if (_obColType == 6) { React_Monitor(curObject); }
		        else if (getobjvariableword(0x30,player) != 90)
		        {
		            //addq.b	#2,obRoutine(a1) ; advance the object's routine counter
                            curObject->Routine = curObject->Routine + 2;
                        }
	                
                        //@invincible:
		        //rts
                    }
                }
            }	
	}
     
        //@next:
	//lea	$40(a1),a1	; next object RAM
        curObject = curObject + 1;
        
    }   //dbf	d6,@loop	; repeat $5F more times

    //moveq	#0,d0
    return 0;

}   //rts	
//; ===========================================================================

//React_Monitor:
void React_Monitor(object *monitor)
{
    //tst.w	obVelY(a0)	; is Sonic moving upwards?
    signed short obVelY = player.VelocityY;

    //bpl.s	@movingdown	; if not, branch
    if (obVelY < 0)
    {
        //move.w	obY(a0),d0
        word obY = player.Y;

	//subi.w	#$10,d0
        word tileAboveY = obY - 16;

	//cmp.w	obY(a1),d0
	//bcs.s	@donothing
        if (tileAboveY > monitor->Y)
        {
	    //neg.w	obVelY(a0)	; reverse Sonic's vertical speed
            player.VelocityY = -player.VelocityY;

	    //move.w	#-$180,obVelY(a1)
            monitor->VelocityY = -0x180;

	    //tst.b	ob2ndRout(a1)
            //bne.s	@donothing
            if (monitor->secondRoutine == 0)
            {
		//addq.b	#4,ob2ndRout(a1) ; advance the monitor's routine counter
                monitor->secondRoutine = monitor->secondRoutine + 4;
            }
	    //rts
        }
    }	
    //; ===========================================================================
    else
    {
        //@movingdown:
        //cmpi.b	#id_Roll,obAnim(a0) ; is Sonic rolling/jumping?
        //bne.s	@donothing
	if (player.Anim == id_Roll)
     	{        
	    //neg.w	obVelY(a0)	; reverse Sonic's y-motion
            player.VelocityY = -player.VelocityY;

	    //addq.b	#2,obRoutine(a1) ; advance the monitor's routine counter
            monitor->Routine = monitor->Routine + 2;
        }
	
    }
    //@donothing:
    //rts	
}

//; ===========================================================================


#define id_ExplosionItem 0x27
word points[4] = { 10, 20, 50, 100 };	//; points awarded div 10

//React_Enemy:
void React_Enemy(object *enemy)
{
    //tst.b	(v_invinc).w	; is Sonic invincible?
    //bne.s	@donthurtsonic	; if yes, branch
    //cmpi.b	#id_Roll,obAnim(a0) ; is Sonic rolling/jumping?
    //bne.w	React_ChkHurt	; if not, branch
    if (v_invinc != 0 || player.Anim == id_Roll)
    {
        //@donthurtsonic:
	//tst.b	obColProp(a1)
        //beq.s	@breakenemy
        if (enemy->ColProp !=0) 
        {
	    //neg.w	obVelX(a0)	; repel Sonic
            //neg.w	obVelY(a0)
            //asr	obVelX(a0)
	    //asr	obVelY(a0)
            player.VelocityX = -player.VelocityX/2;
            player.VelocityY = -player.VelocityY/2;

	    //move.b	#0,obColType(a1)
            enemy->ColType = 0;

	    //subq.b	#1,obColProp(a1)
            enemy->ColProp = enemy->ColProp - 1;

	    //bne.s	@flagnotclear
            if (enemy->ColProp == 0)
            {
		//bset	#7,obStatus(a1)
                enemy->Status = enemy->Status | 0x80;
            }
	    
            //@flagnotclear:
	    //rts
        }   //; ===========================================================================
        else
        {
            //@breakenemy:
	    //bset	#7,obStatus(a1)
            enemy->Status = enemy->Status | 0x80;

	    //moveq	#0,d0
	    //move.w	(v_itembonus).w,d0
            word bonusCount = v_itembonus;

	    //addq.w	#2,(v_itembonus).w ; add 2 to item bonus counter
            v_itembonus = v_itembonus + 2;

	    //cmpi.w	#6,d0
            if (bonusCount > 6)
            {
		//bcs.s	@bonusokay
		//moveq	#6,d0		; max bonus is lvl6
                bonusCount = 6;
            }
    
	    //@bonusokay:
	    //move.w	d0,$3E(a1)
            ptrsetobjvariableword(0x3E, enemy, bonusCount);

	    //move.w	@points(pc,d0.w),d0
            word numPoints = points[bonusCount/2];

	    //cmpi.w	#$20,(v_itembonus).w ; have 16 enemies been destroyed?
            //bcs.s	@lessthan16	; if not, branch
            if (v_itembonus >= 32)
            {
		//move.w	#1000,d0	; fix bonus to 10000
                bonusCount = 1000;

		//move.w	#$A,$3E(a1)
                ptrsetobjvariableword(0x3E, enemy, 10);
            }

	    //@lessthan16:
	    //bsr.w	AddPoints
            //AddPoints();

	    //move.b	#id_ExplosionItem,0(a1) ; change object to explosion
	    enemy->ID = id_ExplosionItem;

            //move.b	#0,obRoutine(a1)
            enemy->Routine = 0;

	    //tst.w	obVelY(a0)
            //bmi.s	@bouncedown
            if (player.VelocityY < 0)
            {
		//@bouncedown:
		//addi.w	#$100,obVelY(a0)
		player.VelocityY = player.VelocityY + 256;

                //rts
            }
	
	    //move.w	obY(a0),d0
	    //cmp.w	obY(a1),d0
            //bcc.s	@bounceup
            else if (player.Y > enemy->Y)
            {
                //@bounceup:
		//subi.w	#$100,obVelY(a0)
		player.VelocityY = player.VelocityY - 256;
                
                //rts
            }	
	
            else
            {	
	        //neg.w	obVelY(a0)
                player.VelocityY = -player.VelocityY;
		
                //rts
            }   //; ===========================================================================
        }
    }
    else
        React_ChkHurt(enemy);
}
void React_Caterkiller(object *caterkiller)	
{
    //React_Caterkiller:
    //bset	#7,obStatus(a1)
    caterkiller->Status = caterkiller->Status | 0x80;

    //React_ChkHurt...
    React_ChkHurt(caterkiller);
}   //; ===========================================================================
    
long React_ChkHurt(object *enemy)
{
    //React_ChkHurt:
    //tst.b	(v_invinc).w	; is Sonic invincible?
    //beq.s	@notinvincible	; if not, branch
    if (v_invinc != 0)
    {
        //@isflashing:
	//moveq	#-1,d0
        return -1;
     
        //rts	
    }   //; ===========================================================================

    //@notinvincible:
    //nop
    asm volatile("nop");
	
    //tst.w	$30(a0)		; is Sonic flashing? 
    //bne.s	@isflashing	; if yes, branch
    if (getobjvariableword(0x30, player) != 0)
	return -1;
	
    //movea.l	a1,a2
    object *victim = enemy;

    #ifdef SONIC_INJURY
    HurtSonic(victim);
    #endif

}   //; End of function ReactToItem
//; continue straight to HurtSonic


//; ===========================================================================

//@sizes:		;   width, height
byte sizes[72] = {
0x14, 0x14, 0xC, 0x14, 0x14, 0xC, 4,  0x10, 0xC, 0x12, 0x10, 0x10,
   6,    6,0x18,  0xC,  0xC,0x10,0x10, 0xC,   8,    8, 0x14, 0x10,
0x14,    8, 0xE,  0xE, 0x18,0x18,0x28,0x10,0x10, 0x18,    8, 0x10,
0x20, 0x70,0x40, 0x20, 0x80,0x20,0x20,0x20,   8,    8,    4,    4,
0x20,    8, 0xC,  0xC,    8,   4,0x18,   4,0x28,    4,    4,    8,	
   4, 0x18,   4, 0x28,    4,0x20,0x18,0x18, 0xC, 0x18, 0x48,    8
};

//; ===========================================================================

bool TestCollision(object *obj, byte obColType, word d4, word playerHeight, signed short playerXBehind, signed short playerYAbove)
{
    //@proximity:
    //andi.w	#$3F,d0
    //add.w	d0,d0
    word colSizeIndex = (obColType & 0x3F) * 2;

    //lea	@sizes-2(pc,d0.w),a2
    byte *colSizePtr = &sizes[colSizeIndex - 2];

    //moveq	#0,d1
    //move.b	(a2)+,d1
    byte colWidthHalf = *(colSizePtr++);

    //move.w	obX(a1),d0
    word colObX = obj->X;

    //sub.w	d1,d0
    //sub.w	d2,d0
    signed short distPlayerObjLeft = (colObX - colWidthHalf) - playerXBehind;

    //bcc.s	@outsidex	; branch if not touching
    if (distPlayerObjLeft < 0)
    {
        //add.w	d1,d1
        word colWidth = colWidthHalf * 2;

	//add.w	d1,d0
        signed short distPlayerObjRight = distPlayerObjLeft + colWidth;

        //bcs.s	@withinx	; branch if touching
        if (distPlayerObjRight < 0)
        {
            //bra.w	@next
            return false;
        }
        //; ===========================================================================
    }
    else
    {
        //@outsidex:
        //cmp.w	d4,d0
        if (distPlayerObjLeft > d4)
        {
	    //bhi.w	@next
            return false;
        }
    }
    
    //@withinx:
    //moveq	#0,d1
    //move.b	(a2)+,d1
    byte colHeightHalf = *(colSizePtr++);
    
    //move.w	obY(a1),d0
    word colObY = obj->Y;

    //sub.w	d1,d0
    //sub.w	d3,d0
    signed short distPlayerObjTop = (colObY - colHeightHalf) - playerYAbove;

    //bcc.s	@outsidey	; branch if not touching
    if (distPlayerObjTop < 0)
    {
        //add.w	d1,d1
        word colHeight = colHeightHalf * 2;

	//add.w	d0,d1
        signed short distPlayerObjBtm = distPlayerObjTop + colHeight;

	//bcs.s	@withiny	; branch if touching
        if (distPlayerObjBtm < 0)
        {
	    //bra.w	@next
            return false;
        }
        //; ===========================================================================
    }
    else
    {
        //@outsidey:
	//cmp.w	d5,d0
        if (distPlayerObjTop > playerHeight)
        {
            //bhi.w	@next
            return false;
        }
    }
    
    return true;
}






//; ---------------------------------------------------------------------------
//; Hurting Sonic	subroutine
//; ---------------------------------------------------------------------------

#include "objectsystemNEWER.h"
 
//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
extern byte v_shield;
extern word v_rings;
extern word f_debugmode;

#define id_RingLoss 0x37

//HurtSonic:
long HurtSonic(object *victim)
{
    //tst.b	(v_shield).w	; does Sonic have a shield?
    //bne.s	@hasshield	; if yes, branch
    if (v_shield == 0)
    {
        //tst.w	(v_rings).w	; does Sonic have any rings?
        //beq.w	@norings	; if not, branch
        if (v_rings == 0)
        {
            //@norings:
	    //tst.w	(f_debugmode).w	; is debug mode	cheat on?
	    //bne.w	@hasshield	; if yes, branch
            if (f_debugmode == 0) { return 0; /*KillSonic();*/ }
        }
        else
        {
	    //jsr	FindFreeObj
            object *ringLoss = FindFreeObj();

	    //bne.s	@hasshield
            if (ringLoss->ID == 0)
            {
	        //move.b	#id_RingLoss,0(a1) ; load bouncing multi rings object
	        ringLoss->ID = id_RingLoss;
                 
                //move.w	obX(a0),obX(a1)
                ringLoss->X = player.X;

	        //move.w	obY(a0),obY(a1)
                ringLoss->Y = player.Y;
            }
        }
    }
        
    //@hasshield:
    //move.b	#0,(v_shield).w	; remove shield
    v_shield = 0;

    //move.b	#4,obRoutine(a0)
    player.Routine = 4;

    //bsr.w	Sonic_ResetOnFloor
    Sonic_ResetOnFloor();

    //bset	#1,obStatus(a0)
    player.Status = player.Status | 2;

    //move.w	#-$400,obVelY(a0) ; make Sonic bounce away from the object
    player.VelocityY = -0x400;

    //move.w	#-$200,obVelX(a0)
    player.VelocityX = -0x200;

    //btst	#6,obStatus(a0)	; is Sonic underwater?
    //beq.s	@isdry		; if not, branch
    if ((player.Status & 64) == 64)
    {
        //move.w	#-$200,obVelY(a0) ; slower bounce
        player.VelocityY = -0x200;

        //move.w	#-$100,obVelX(a0)
        player.VelocityX = -0x100;
    }

    //@isdry:
    //move.w	obX(a0),d0
    word playerX = player.X;

    //cmp.w	obX(a2),d0
    //bcs.s	@isleft		; if Sonic is left of the object, branch
    if (playerX > victim->X)
    {
        //neg.w	obVelX(a0)	; if Sonic is right of the object, reverse
        player.VelocityX = -player.VelocityX;
    }

    //@isleft:
    //move.w	#0,obInertia(a0)
    player.Inertia = 0;

    //move.b	#id_Hurt,obAnim(a0)
    player.Anim = id_Hurt;

    //move.w	#120,$30(a0)	; set temp invincible time to 2 seconds
    setobjvariableword(0x30, player, 120);

    //move.w	#sfx_Death,d0	; load normal damage sound
    //cmpi.b	#id_Spikes,(a2)	; was damage caused by spikes?
    //bne.s	@sound		; if not, branch
    //cmpi.b	#id_Harpoon,(a2) ; was damage caused by LZ harpoon?
    //bne.s	@sound		; if not, branch
    //move.w	#sfx_HitSpikes,d0 ; load spikes damage sound
    //@sound:
    //jsr	(PlaySound_Special).l
	
    //moveq	#-1,d0
    return -1;
     
    //rts	
}   //; ===========================================================================



/*
; ---------------------------------------------------------------------------
; Subroutine to	kill Sonic
; ---------------------------------------------------------------------------

; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


KillSonic:
		tst.w	(v_debuguse).w	; is debug mode	active?
		bne.s	@dontdie	; if yes, branch
		move.b	#0,(v_invinc).w	; remove invincibility
		move.b	#6,obRoutine(a0)
		bsr.w	Sonic_ResetOnFloor
		bset	#1,obStatus(a0)
		move.w	#-$700,obVelY(a0)
		move.w	#0,obVelX(a0)
		move.w	#0,obInertia(a0)
		move.w	obY(a0),$38(a0)
		move.b	#id_Death,obAnim(a0)
		bset	#7,obGfx(a0)
		move.w	#sfx_Death,d0	; play normal death sound
		cmpi.b	#id_Spikes,(a2)	; check	if you were killed by spikes
		bne.s	@sound
		move.w	#sfx_HitSpikes,d0 ; play spikes death sound

	@sound:
		jsr	(PlaySound_Special).l

	@dontdie:
		moveq	#-1,d0
		rts	
; End of function KillSonic


; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


React_Special:
		move.b	obColType(a1),d1
		andi.b	#$3F,d1
		cmpi.b	#$B,d1		; is collision type $CB	?
		beq.s	@caterkiller	; if yes, branch
		cmpi.b	#$C,d1		; is collision type $CC	?
		beq.s	@yadrin		; if yes, branch
		cmpi.b	#$17,d1		; is collision type $D7	?
		beq.s	@D7orE1		; if yes, branch
		cmpi.b	#$21,d1		; is collision type $E1	?
		beq.s	@D7orE1		; if yes, branch
		rts	
; ===========================================================================

@caterkiller:
		bra.w	React_Caterkiller
; ===========================================================================

@yadrin:
		sub.w	d0,d5
		cmpi.w	#8,d5
		bcc.s	@normalenemy
		move.w	obX(a1),d0
		subq.w	#4,d0
		btst	#0,obStatus(a1)
		beq.s	@noflip
		subi.w	#$10,d0

	@noflip:
		sub.w	d2,d0
		bcc.s	@loc_1B13C
		addi.w	#$18,d0
		bcs.s	@loc_1B140
		bra.s	@normalenemy
; ===========================================================================

	@loc_1B13C:
		cmp.w	d4,d0
		bhi.s	@normalenemy

	@loc_1B140:
		bra.w	React_ChkHurt
; ===========================================================================

	@normalenemy:
		bra.w	React_Enemy
; ===========================================================================

@D7orE1:
		addq.b	#1,obColProp(a1)
		rts	
; End of function React_Special
*/


//Obj44_SolidWall:			; XREF: Obj44_Solid
void Obj44_SolidWall(object *obj, word width, word jumpHeight)
{
    signed short distWallX, distWallY;
    //bsr.w	Obj44_SolidWall2
    long wallCollision = Obj44_SolidWall2(obj, width, jumpHeight, distWallX, distWallY);

    //beq.s	loc_8AA8
    if (wallCollision == 0)
    {
        //loc_8AA8:
	//btst	#5,obStatus(a0)
        //beq.s	locret_8AC2
        if ((obj->Status & 32) != 0)
        {
	    //move.w	#id_Run,obAnim(a1)
            player.Anim = id_Run;

            //loc_8AB6:
	    //bclr	#5,obStatus(a0)
            obj->Status = obj->Status - (obj->Status & 32);
        
	    //bclr	#5,obStatus(a1)
            player.Status = player.Status - (player.Status & 32);
        }
 
        //locret_8AC2:
	//rts	
        //; ===========================================================================
    }
    //bmi.w	loc_8AC4
    else if (wallCollision > 0)
    {
        //tst.w	d0
        //beq.w	loc_8A92
        if (distWallX != 0)
        {
	    //bmi.s	loc_8A7C      (NEG)
              //loc_8A7C:
	      //tst.w	obVelX(a1)    
	        //bpl.s	loc_8A92       VELX >= 0 
                //(bmi loc_8A82)       VELX < 0

            //tst.w	obVelX(a1)    (POS)
	      //bmi.s	loc_8A92       VELX < 0
	      //bra.s	loc_8A82       VELX >=0
            
              //tst.w	obVelX(a1)   
              //bmi.s	loc_8A92
	      //bra.s	loc_8A82
            if ( ((distWallX < 0) && (player.VelocityX < 0)) || ((distWallX > 0) && (player.VelocityX >= 0)) )
            {
                //loc_8A82:
		//sub.w	d0,obX(a1)
                player.X = player.X - distWallX;

		//move.w	#0,obInertia(a1)
                player.Inertia = 0;

		//move.w	#0,obVelX(a1)
                player.VelocityX = 0;
            }
        }

        //loc_8A92:
        //btst	#1,obStatus(a1)
        //bne.s	loc_8AB6
        if ((player.Status & 2) == 2)
        {
            //bset	#5,obStatus(a1)
	    player.Status = player.Status | 32;
	
	    //bset	#5,obStatus(a0)
            obj->Status = obj->Status | 32;		
        }   //rts	
        //; ===========================================================================
        else
        {
             //loc_8AB6:
	    //bclr	#5,obStatus(a0)
            obj->Status = obj->Status - (obj->Status & 32);
        
	    //bclr	#5,obStatus(a1)
            player.Status = player.Status - (player.Status & 32);
        }
    }
    else
    {
        //loc_8AC4:
	//tst.w	obVelY(a1)
        //bpl.s	locret_8AD8
        //tst.w	d3
	//bpl.s	locret_8AD8
        if ( (player.VelocityY < 0) && (distWallY < 0) )
	{
            //sub.w	d3,obY(a1)
            player.Y = player.Y - distWallY;

	    //move.w	#0,obVelY(a1)
            player.VelocityY = 0;
        }
    }
     
    //locret_8AD8:
    //rts	
}   //; End of function Obj44_SolidWall


//; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


//Obj44_SolidWall2:			; XREF: Obj44_SolidWall
long Obj44_SolidWall2(object *obj, word width, word jumpHeight, signed short &distPlayerObjL, signed short &distPlayerObjT)
{
    #define distPlayerObjR distPlayerObjL 
    #define distPlayerObjB distPlayerObjT 

    //lea	(v_player).w,a1
   
    //move.w	obX(a1),d0
    //sub.w	obX(a0),d0
    signed short distPlayerObjCX = player.X - obj->X;

    //add.w	d1,d0
    distPlayerObjR = distPlayerObjCX + width;

    //bmi.s	loc_8B48
    if (distPlayerObjR >= 0)
    {
        //move.w	d1,d3
        //add.w	d3,d3
        word fullWidth = width * 2;

	//cmp.w	d3,d0
        //bhi.s	loc_8B48
        if (distPlayerObjR < fullWidth)
        {
	    //move.b	obHeight(a1),d3
	    //ext.w	d3
            word playerHeight = player.Height;

	    //add.w	d3,d2
            word height = playerHeight + jumpHeight;

	    //move.w	obY(a1),d3
            //sub.w	obY(a0),d3
            signed short distPlayerObjCY = player.Y - obj->Y;

	    //add.w	d2,d3
            distPlayerObjB = distPlayerObjCY + height;
       
	    //bmi.s	loc_8B48
            if (distPlayerObjB >= 0)
            {
	        //move.w	d2,d4
                //add.w	d4,d4
                word fullHeight = height * 2;

		//cmp.w	d4,d3
                //bhs.s	loc_8B48
                if (distPlayerObjB < fullHeight)
                {
		    //tst.b	(f_lockmulti).w
		    //bmi.s	loc_8B48
                    //cmpi.b	#6,(v_player+obRoutine).w
		    //bhs.s	loc_8B48
		    //tst.w	(v_debuguse).w
		    //bne.s	loc_8B48
                    if ((!f_lockmulti) && (player.Routine < 6) && (v_debuguse == 0))
                    {
                        //move.w	d0,d5
                        signed short distPlayerObjX = distPlayerObjR;

		        //cmp.w	d0,d1
                        //bhs.s	loc_8B30
                        if (width < distPlayerObjR)
                        {
		            //add.w	d1,d1
                            word _fullWidth = width * 2;
      
		            //sub.w	d1,d0
                            distPlayerObjL = distPlayerObjR - _fullWidth;
                            
		            //move.w	d0,d5
		            //neg.w	d5
                            distPlayerObjX = -distPlayerObjL;
                        }
                        
                        //loc_8B30:
		        //move.w	d3,d1
                        signed short distPlayerObjY = distPlayerObjB;

		        //cmp.w	d3,d2
                        //bhs.s	loc_8B3C
                        if (height < distPlayerObjB)
                        { 
                            //sub.w	d4,d3
                            distPlayerObjT = distPlayerObjB - fullHeight;

                            //move.w	d3,d1
                            //neg.w	d1
                            distPlayerObjY = -distPlayerObjT;
                        }

                        //loc_8B3C:
		        //cmp.w	d1,d5
                        //bhi.s	loc_8B44
                        if (distPlayerObjX < distPlayerObjY)
                        {
		            //moveq	#1,d4
                            return 1;
                        }   //rts	
                        //; ===========================================================================
                        //loc_8B44:
                        else
                        {
                            //moveq	#-1,d4
                            return -1;
                        }   //rts	
                        //; ===========================================================================
                    }
                }
            }
        }
    }
    
    //loc_8B48:
    //moveq	#0,d4
    return 0;
 
}   //rts	
//; End of function Obj44_SolidWall2
//; ===========================================================================

